package filemanager;

import java.io.File;
import java.io.IOException;
import java.sql.SQLException;
import java.util.HashMap;

import core.Server;

public class FileManager {

	String programName;
	String extenzion;
	
	File programDir;
	File fileDir;
	File releaseDir;
	File tempDir;
	
	HashMap<String, String> lockOwners;
	
	public FileManager(String programName, String extenzion)
	{
		String serverMainDir = Server.getInstance().getConfigs().get(2);
		String serverTempDir = Server.getInstance().getConfigs().get(5);
		
		this.programName = programName;
		this.extenzion = extenzion;
		
		this.programDir = new File(serverMainDir + "/" + this.programName);
		this.fileDir = new File(this.programDir, "files");
		this.releaseDir = new File(this.programDir, "releases");
		
		this.tempDir = new File(serverMainDir + "/" + serverTempDir + "/" +this.programName);
		
		this.lockOwners = new HashMap<String, String>();
	}

	public boolean addNewRelease(String fileName, int lastRelease) throws SQLException, IOException
	{
		// TODO: Se il copyFile diventa booleana bisogna gestire il return false
		
		String tempFile = this.tempDir + "/" + fileName + "." + this.extenzion;
		String currentFile = this.fileDir + "/" + fileName + "." + this.extenzion;
		String relFile = this.releaseDir + "/" + fileName + ".r" + String.valueOf(lastRelease);

		FileFunctions.copyFile(currentFile, relFile);
		FileFunctions.copyFile(tempFile, currentFile);

		return true;
	}
/*
	public String[] getFileList()
	{		
		return this.fileDir.list();
	}
	
	public String[] getReleasesOfFile(String fileName)
	{
		return this.releaseDir.list(new FileNameFilter(fileName));
	}
*/	
	public synchronized boolean requestLock(String fileName, String userId)
	{
		if(this.lockOwners.get(fileName) != null) return false;
		this.lockOwners.put(fileName, userId);
		
		return true;
	}
	
	public synchronized void releaseLock(String fileName)
	{
		this.lockOwners.remove(fileName);		
	}
	
	public synchronized boolean newFile(String newFileName)
	{
		// TODO: Non deve esiste un file con quel nome !!!
		
		try {
			FileFunctions.copyFile(this.programDir.getPath() + "/newFileTemplate." + extenzion, this.fileDir.getPath() + "/" + newFileName + "." + extenzion);
			return true;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		}
	}
	
	public synchronized boolean removeFile(String fileName)
	{
		// TODO: Se alcuni files vengono eliminati ed altri no??
		
		File file = new File(this.fileDir.getAbsolutePath() + "/" + fileName + "." + extenzion);
		if(!file.delete())
			return false;
		
		File []releasesToDelete = this.releaseDir.listFiles(new FileNameFilter(fileName));
		for (int i = 0; i < releasesToDelete.length; i++)
			if(!file.delete())
				return false;
		
		return true;
	}
	
	//TODO: ELIMINARE IL VECCHIO FILE DALLA CARTELLA FILES E AGGIUGNERE IL NUOVO
	public synchronized boolean addRelease(String fileName, int releaseNumber)
	{
		try {
			FileFunctions.copyFile(this.fileDir.getPath() + "/" + fileName + "." + extenzion, this.releaseDir.getPath() + "/" + fileName + ".r" + releaseNumber);
			
			return true;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		}
	}
	
	public boolean createStructure(String newFileTemplate)
	{
		try{
			//TODO: E SE NON CREA LE CARTELLE ???
			
			this.programDir.mkdir();
			this.fileDir.mkdir();
			this.releaseDir.mkdir();
						
			FileFunctions.copyFile(newFileTemplate, this.programDir.getPath() + "/newFileTemplate." + this.extenzion);
			
			return true;
		} catch (NullPointerException e) {
			// TODO: eccezione, bisogna rimuovere la struttura creata a metà!
			return false;
		} catch (IOException e) {
			// TODO eccezione, bisogna rimuovere la struttura creata a metà!
			e.printStackTrace();
			return false;
		}
	}

	public boolean removeStructure()
	{
		return FileFunctions.deleteDirectory(this.programDir);
	}

	public String getProgramName() {
		return programName;
	}

	public String getExtenzion() {
		return extenzion;
	}

	public File getProgramDir() {
		return programDir;
	}

	public File getFileDir() {
		return fileDir;
	}

	public File getReleaseDir() {
		return releaseDir;
	}

	public HashMap<String, String> getLockOwners() {
		return lockOwners;
	}
}